﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sern.Abstracts.Tracker.DataContracts;
using Sern.Common;
using Sern.Common.Fakes;
using Sern.ServiceImplementation.TrackerDefinition;
using Sern.ServiceImplementation.TrackerDefinition.Data;
using Microsoft.Practices.Unity;
using Sern.ServiceImplementation.TrackerDefinition.Service;

namespace Sern.Test.ServiceImplementation.TrackerDefinition.Service
{
    [TestClass]
    public class Tracker_ActiveClientSearch_LeastBusyClient
    {
        [TestInitialize]
        public void Init()
        {
            ComponentLocator.Reset();

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<Client>());

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<KeyTree>());

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<KeyAtClientLog>());

            ComponentLocator.Unity.RegisterTestInstance(Guid.NewGuid(), "JobId");

            Guid client1Id, client2Id, client3Id;

            client1Id = Guid.NewGuid();
            client2Id = Guid.NewGuid();
            client3Id = Guid.NewGuid();

            ComponentLocator.Unity.RegisterInstance("TheCorrectClientId", client1Id);

            ComponentLocator.Unity.Resolve<IRepository<KeyAtClientLog>>()
                .AddMany(
                    new KeyAtClientLog[]{
                        new KeyAtClientLog
                            {
                                ClientId = client3Id,
                                KeyId = Guid.NewGuid(),
                                RedundancyKey = Guid.NewGuid(),
                                State = (int) ProcessingStage.Processing,
                                Id = Guid.NewGuid()
                            },
                        new KeyAtClientLog
                            {
                                ClientId = client2Id,
                                KeyId = Guid.NewGuid(),
                                RedundancyKey = Guid.NewGuid(),
                                State = (int) ProcessingStage.Processing,
                                Id = Guid.NewGuid()
                            },
                        new KeyAtClientLog
                            {
                                ClientId = client2Id,
                                KeyId = Guid.NewGuid(),
                                RedundancyKey = Guid.NewGuid(),
                                State = (int) ProcessingStage.Processing,
                                Id = Guid.NewGuid()
                            },
                    });

            ComponentLocator.Unity.Resolve<IRepository<Client>>()
                .AddMany(new[]
                    {
                        new ClientStatusInfo
                            {
                                Id = client1Id,
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost1",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Splitter
                            },
                        new ClientStatusInfo
                            {
                                Id = client2Id,
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost2",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Splitter
                            },
                        new ClientStatusInfo
                            {
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Id = client3Id,
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost3",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Splitter
                            },
                    });
        }

        //TODO: Test with various active date.
        //TODO: Test with varoious last ping status.
        //TODO: Test with filter and non filter. ***
        //TODO: Test with various processing count.
        //TODO: Test with various shapes.

        [TestMethod]
        public void TestOnlyActiveClientIsReturned()
        {
            var jobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId");

            var activeClientInfo = new Tracker().FindActiveClientInfo(jobId, ClientType.Splitter,
                Guid.NewGuid(),
                Guid.NewGuid(),
                "keyShape",
                "valueShape"
            );

            Assert.AreEqual(
                ComponentLocator.Unity.Resolve<Guid>("TheCorrectClientId"), activeClientInfo.Id);
        }
    }
}
